﻿/*   
    Copyright (C) 2009 Galaktika Corporation ZAO

    This file is a part of Galaktika.BusinessMonitor
 
    Galaktika.BusinessMonitor is a free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
      
    You should have received a copy of the GNU General Public License
    along with Galaktika.BusinessMonitor.  If not, see <http://www.gnu.org/licenses/>.
  
    If GPL v.3 is not suitable for your products or company,
    Galaktika Corp provides Galaktika.BusinessMonitor under a flexible commercial license
    designed to meet your specific usage and distribution requirements.
    If you have already obtained a commercial license from Galaktika Corp,
    you can use this file under those license terms.
*/

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Net;
using System.ServiceModel;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Galaktika.BI.Runtime.Services;
using Galaktika.BI.Silverlight.Services;

namespace Galaktika.BI.Silverlight.Controls.BallGame
{
    [ScriptableType]
    public partial class Game : UserControl
    {
        public const int BoardWidth = 20;
        public const int BoardHeight = 20;
        public const int BubbleSize = 15;
        public const int NumColors = 3;
        public const string Level = "Easy";
        public const int ControlWidth = 250;
        public const int ControlHeight = 200;

        // Fields
        private int boardHeight;
        private int boardWidth;
        //internal Button btnSubmitScore;
        private int bubbleSize;
        //internal Canvas canvasBoard;
        //internal StackPanel enterScorePanel;
        //internal Storyboard fadeInBoard;
        //internal Storyboard fadeInText;
        //internal Storyboard fadeOutBoard;
        //internal Storyboard fadeWait;
        //internal Canvas LayoutRoot;
        //internal TextBlock lblYourName;
        private string level;
        //internal StackPanel mainGamePanel;
        private int nrOfColors;
        //internal RotateTransform rotateBoard;
        //internal ScaleTransform scaleBoard;
        private int score;
        private bool sendScore;
        //internal Slider slider;
        //internal MediaElement soundDrop;
        //internal TextBlock txtError;
        //internal TextBox txtInput;
        //internal TextBlock txtScore;
        //internal StackPanel waitPanel;

        // Events
        [ScriptableMember]
        public event EventHandler CallbackToBrowser;

        // Methods
        public Game() : 
            this(true)
        {
            
        }
        public Game(bool startNewGame)
        {
            this.InitializeComponent();
            this.NewGameButton.Content = Localization.Btn_NewGame;
            if (startNewGame)
            {
                this.InitializeGame(BoardWidth, BoardHeight, BubbleSize, NumColors, Level, ControlWidth, ControlHeight);
                this.NewGameButton.Visibility = Visibility.Collapsed;
            }
            else
            {
                this.slider.Visibility = Visibility.Collapsed;
                this.NewGameButton.Visibility = Visibility.Visible;
            }
        }

        private void InitializeGame(int boardWidth1, int boardHeight1, int bubbleSize1, int nrOfColors1, string level1, double controlWidth1, double controlHeight1)
        {           
            base.Loaded += new RoutedEventHandler(this.Game_Loaded);
            try
            {
                base.Width = controlWidth1;
                base.Height = controlHeight1;
                this.LayoutRoot.Width = controlWidth1;
                this.LayoutRoot.Height = controlHeight1;
                this.mainGamePanel.Width = controlWidth1;
                this.enterScorePanel.Width = controlWidth1;
                this.waitPanel.Width = controlWidth1;
                this.boardWidth = boardWidth1;
                this.boardHeight = boardHeight1;
                this.bubbleSize = bubbleSize1;
                this.nrOfColors = nrOfColors1;                
                this.level = level1;
                this.NewGameButton.Visibility = System.Windows.Visibility.Collapsed;
                this.slider.Visibility = Visibility.Visible;
                this.lblYourName.Text = Localization.Lbl_InputName;
                this.btnSubmitScore.Content = Localization.Btn_Submit;
                this.txtWait.Text = Localization.Lbl_Wait;

            }
            catch (Exception exception)
            {
                this.HandleException(exception);
            }
        }
    
        private void board_BubblesRemoved(int count)
        {
            try
            {
                if (this.soundDrop.CanSeek)
                {
                    this.soundDrop.Position = new TimeSpan();
                }
                this.soundDrop.Play();
                this.score += this.count2points(count);
                this.SetScore(this.score);
            }
            catch (Exception exception)
            {
                this.HandleException(exception);
            }
        }

        private void board_GameOver(Board board)
        {
            try
            {
                if (board.IsBoardClear())
                {
                    this.score += 500;
                }
                this.SetScore(this.score);
                this.fadeOutBoard.Begin();
                this.enterScorePanel.Visibility = Visibility.Visible;
                this.txtInput.Text = "";
                this.fadeInText.Begin();
                this.txtInput.Focus();
            }
            catch (Exception exception)
            {
                this.HandleException(exception);
            }
        }

        private void btnSubmitScore_Click(object sender, RoutedEventArgs e)
        {
            if ((this.txtInput.Text.Trim() != string.Empty) && !this.sendScore)
            {
                try
                {
                    ScoresSoapClient client = new ScoresSoapClient();
                    //Uri documentUri = HtmlPage.Document.DocumentUri;
                    //string uri = new UriBuilder(documentUri.Scheme, documentUri.Host, documentUri.Port, "/Scores.asmx").Uri.ToString();
                    //client.Endpoint.Address = new EndpointAddress(uri);
                    client.AddScoreCompleted += new EventHandler<AsyncCompletedEventArgs>(this.scoresClient_AddScoreCompleted);
                    int date = 0;
                    int time = 0;
                    int code = this.BuildCheckCode(this.score, this.boardWidth, this.boardHeight, this.nrOfColors, out date, out time);
                    this.sendScore = true;
                    client.AddScoreAsync(this.boardWidth.ToString(), this.boardHeight.ToString(), this.nrOfColors.ToString(), this.score.ToString(), date.ToString(), time.ToString(), code.ToString(), this.txtInput.Text);                    
                    this.waitPanel.Visibility = Visibility.Visible;
                    this.txtInput.Visibility = Visibility.Collapsed;
                    this.enterScorePanel.Visibility = System.Windows.Visibility.Visible;
                    //this.fadeWait.Begin();                    
                }
                catch (Exception exception)
                {
                    this.HandleException(exception);
                }
            }
        }

        private void ShowScores()                
        {
            ScoresSoapClient client = new ScoresSoapClient();
            client.GetTop5Completed += new EventHandler<GetTop5CompletedEventArgs>(client_GetTop5Completed);
            client.GetTop5Async();
        }

        private void client_GetTop5Completed(object sender, GetTop5CompletedEventArgs e)
        {
            this.enterScorePanel.Visibility = System.Windows.Visibility.Collapsed;
            this.scoresPanel.Visibility = System.Windows.Visibility.Visible;
            var result = e.Result;
            
            //this.scoresPanel.Children.Clear();
            int i = 1;
            foreach (var s in result)
            {                
                StackPanel sp = new StackPanel()
                                    {
                                        Orientation = Orientation.Horizontal,
                                        Height = 20,
                                        HorizontalAlignment = System.Windows.HorizontalAlignment.Center

                                    };
                TextBlock number = new TextBlock()
                                       {
                                           Text = i.ToString() + ".",
                                           Foreground = new SolidColorBrush(Colors.Red),
                                           FontSize = 12,
                                           HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
                                           Width = 20
                                       };
                TextBlock name = new TextBlock()
                                     {
                                         Text = s.Name,
                                         Foreground = new SolidColorBrush(Colors.Red),
                                         FontSize = 12,
                                         HorizontalAlignment = System.Windows.HorizontalAlignment.Right,
                                         Width = 100
                                     };
                TextBlock ochko = new TextBlock()
                                      {
                                          Text = "   " + s.Score,
                                          Foreground = new SolidColorBrush(Colors.Red),
                                          FontSize = 12,
                                          HorizontalAlignment = System.Windows.HorizontalAlignment.Right,
                                          Width  = 60
                                    };
                sp.Children.Add(number);
                sp.Children.Add(name);
                sp.Children.Add(ochko);
                this.scoresPanel.Children.Add(sp);
                i++;                    
            }            
        }

        protected int BuildCheckCode(int score, int width, int height, int colors, out int date, out int time)
        {
            DateTime now = DateTime.Now;
            date = 0;
            date += 0x2710 * now.Year;
            date += 100 * now.Month;
            date += now.Day;
            time = 0;
            time += 0x2710 * now.Hour;
            time += 100 * now.Minute;
            time += now.Second;
            return ((((((score * 2) ^ (width * 4)) ^ (height * 8)) ^ (colors * 0x10)) ^ (time * 0x100)) ^ date);
        }

        private int count2points(int count)
        {
            int num = 0;
            for (int i = 1; i <= count; i++)
            {
                num += i;
            }
            return num;
        }

        private void Game_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                Board board = new Board(this.canvasBoard, this.boardWidth, this.boardHeight, this.bubbleSize, this.nrOfColors);
                board.BubblesRemoved += new BubblesRemovedEventHandler(this.board_BubblesRemoved);
                board.GameOver += new GameOverEventHandler(this.board_GameOver);
                this.score = 0;
                this.SetScore(this.score);
                this.rotateBoard.CenterX = this.canvasBoard.Width / 2.0;
                this.rotateBoard.CenterY = this.canvasBoard.Height / 2.0;
                this.scaleBoard.CenterX = this.canvasBoard.Width / 2.0;
                this.scaleBoard.CenterY = this.canvasBoard.Height / 2.0;
                this.fadeInBoard.Begin();
            }
            catch (Exception exception)
            {
                this.HandleException(exception);
            }
        }

        protected virtual void HandleException(Exception ex)
        {
            if (this.txtError == null)
            {
                throw ex;
            }
            this.txtError.Visibility = Visibility.Visible;
            this.txtError.Text = Localization.Msg_Error +":" + ex.ToString();
        }

        //[DebuggerNonUserCode]
        //public  void InitializeComponent()
        //{
        //    if (!this._contentLoaded)
        //    {
        //        this._contentLoaded = true;
        //        Application.LoadComponent(this, new Uri("/Bubbles.SilverlightGame;component/Game.xaml", UriKind.Relative));
        //        this.LayoutRoot = (Canvas)base.FindName("LayoutRoot");
        //        this.fadeInBoard = (Storyboard)base.FindName("fadeInBoard");
        //        this.fadeOutBoard = (Storyboard)base.FindName("fadeOutBoard");
        //        this.fadeInText = (Storyboard)base.FindName("fadeInText");
        //        this.fadeWait = (Storyboard)base.FindName("fadeWait");
        //        this.txtError = (TextBlock)base.FindName("txtError");
        //        this.mainGamePanel = (StackPanel)base.FindName("mainGamePanel");
        //        this.slider = (Slider)base.FindName("slider");
        //        this.txtScore = (TextBlock)base.FindName("txtScore");
        //        this.canvasBoard = (Canvas)base.FindName("canvasBoard");
        //        this.rotateBoard = (RotateTransform)base.FindName("rotateBoard");
        //        this.scaleBoard = (ScaleTransform)base.FindName("scaleBoard");
        //        this.soundDrop = (MediaElement)base.FindName("soundDrop");
        //        this.enterScorePanel = (StackPanel)base.FindName("enterScorePanel");
        //        this.lblYourName = (TextBlock)base.FindName("lblYourName");
        //        this.txtInput = (TextBox)base.FindName("txtInput");
        //        this.btnSubmitScore = (Button)base.FindName("btnSubmitScore");
        //        this.waitPanel = (StackPanel)base.FindName("waitPanel");
        //    }
        //}

        private void scoresClient_AddScoreCompleted(object sender, AsyncCompletedEventArgs e)
        {
            this.sendScore = false;
            try
            {
                if (e.Error != null)
                {
                    throw e.Error;
                }
                if (this.CallbackToBrowser != null)
                {
                    this.CallbackToBrowser(this, new EventArgs<string>(this.level));
                }
                this.ShowScores();                
            }
            catch (Exception exception)
            {
                this.HandleException(exception);
            }
        }

        private void SetScore(int score)
        {
            this.txtScore.Text = Localization.Msg_YourScore + score.ToString();
        }

        private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            try
            {
                if (this.scaleBoard != null)
                {
                    this.scaleBoard.CenterY = 0.0;
                    this.scaleBoard.ScaleX = e.NewValue;
                    this.scaleBoard.ScaleY = e.NewValue;
                }
            }
            catch (Exception exception)
            {
                this.HandleException(exception);
            }
        }

        private void NewGameButton_Click(object sender, RoutedEventArgs e)
        {
            this.InitializeGame(BoardWidth, BoardHeight, BubbleSize, NumColors, Level, ControlWidth, ControlHeight);                        
        }
    }


}
